package com.mic.yzzn.plc.web.controller;

import com.mic.yzzn.plc.common.control.RMI.*;
import com.mic.yzzn.plc.common.control.datastructure.*;
import com.mic.yzzn.plc.common.ins.datastructure.*;
import com.mic.yzzn.plc.common.ins.datastructure.PLCContactorNumber;
import com.mic.yzzn.plc.common.ins.datastructure.PLCDataRegisterNumber;
import com.mic.yzzn.plc.common.instructions.basic.PLCRequestInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCDataRegisterReadInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCDataRegisterWriteInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCMultipleContactorReadInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCMultipleContactorWriteInstruction;
import com.mic.yzzn.plc.common.toolUtils.*;
import com.mic.yzzn.plc.common.toolUtils.PLCContactorCode;
import com.mic.yzzn.plc.model.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@RestController("plcController")
public class PLCController {

    private static int MULTI_R_POINT_MAX_NUMBER = 8;
    private static int COLLECTOR_QUEUE_NUM = 3;
    private static final String D_NUMBER_KEY = "D_NUMBER_KEY";
    private static final String R_NUMBER_KEY = "R_NUMBER_KEY";
    private static final String ILLEGAL_KEY = "ILLEGAL_KEY";

    /**
     *
     */
    public static int RMIRemoteExceptionCode = 6,
                      RMINotBoundException = 7,
                      RMIMalformedURLException = 8,
                      CannotFindResult = 9;

    /**
     * 将ContactorPoint转换成PLCDataRegisterNumber
     * @param point
     * @return PLCDataRegisterNumber
     */
    private PLCDataRegisterNumber dataRegisterNumberFromContactPoint(ContactPoint point) {

        PLCDataRegisterNumber dNumber = new PLCDataRegisterNumber();

        try {
            dNumber.setBeginBCDDataNumber(point.getPoint());
            dNumber.setEndBCDDataNumber(point.getPoint());
        } catch (Exception e) {
            return null;
        }

        return dNumber;
    }

    /**
     * 将ContactorPoint转换成PLCContactorNumber
     * @param point
     * @return PLCContactorNumber
     */
    private PLCContactorNumber contactorNumberFromContactPoint(ContactPoint point) {

        PLCContactorNumber rNumber = new PLCContactorNumber();
        int length = point.getPoint().length();

        try {
            rNumber.setBCDCode(point.getPoint().substring(0, length - 1));
            rNumber.setHEXCode(point.getPoint().charAt(length - 1));
        } catch (Exception e) {
            return null;
        }

        return rNumber;
    }

    /**
     * 从范围点位中获取R点数据结构数组
     * @param section
     * @return ArrayList<PLCContactorNumber>
     */
    private ArrayList<PLCContactorNumber> contactorNumberListFromContactSection(ContactSection section) {

        int length = section.getStartPoint().length();
        PLCContactorNumber beginNumber = new PLCContactorNumber();
        PLCContactorNumber endNumber = new PLCContactorNumber();
        int range = 0;

        try {
            beginNumber.setBCDCode(section.getStartPoint().substring(0, length));
            beginNumber.setHEXCode(section.getStartPoint().charAt(length));

            endNumber.setBCDCode(section.getEndPoint().substring(0, length));
            endNumber.setHEXCode(section.getEndPoint().charAt(length));

            range = PLCContactorNumber.rangeOf(beginNumber, endNumber);
        } catch (Exception e) {
            return null;
        }

        ArrayList<PLCContactorNumber> result = new ArrayList<PLCContactorNumber>();

        for (int i = 0; i < range; ++i) {
            PLCContactorNumber rNumber = new PLCContactorNumber(beginNumber.getBCDCode(), beginNumber.getHEXCode());
            result.add(rNumber);
            beginNumber.add(1);
        }

        return result;
    }

    /**
     * 从范围点位中获取D点数据结构
     * @param section
     * @return PLCDataRegisterNumber
     */
    private PLCDataRegisterNumber dataRegisterNumberFromContactSection(ContactSection section) {

        PLCDataRegisterNumber dNumber = null;
        try {
            dNumber = new PLCDataRegisterNumber(section.getStartPoint(), section.getEndPoint());
        } catch (Exception e) {
            return null;
        }

        return dNumber;
    }

    /**
     * 将返回的结果转换为PLCData
     * @param data
     * @return
     */
    private PLCPointData plcPointDataFromPlcData(PLCData data) {

        String pointString = data.getDataNumber();

        ContactPointData contactPointData = new ContactPointData(data.getPointType(), pointString, data.getData());

        PLCPointData result = new PLCPointData(
                contactPointData,
                data.getTimestamp(),
                data.getState());

        return result;
    }

    /**
     * 将Web的数据结构转换成PLC采控内核中的数据结构
     * @param pointList 离散点列表
     * @param sectionList 连续点列表
     * @return PLC内核中的数据结构的Map
     */
    private HashMap<String, List> coreDataStructureFromWebDataStructure(List<ContactPoint> pointList , List<ContactSection> sectionList) {

        // 存储转换后的数据结构的数组
        ArrayList<PLCDataRegisterNumber> dPointNumberParam = new ArrayList<PLCDataRegisterNumber>();
        ArrayList<PLCContactorNumber> rPointNumberParam = new ArrayList<PLCContactorNumber>();
        ArrayList<String> invalidPoint = new ArrayList<>();

        if (pointList != null) {
            for (ContactPoint point : pointList) {

                if (point.getType().equals(PLCContactorCode.PLC_INNER_RELAY_CODE)) {
                    PLCContactorNumber rNumber = contactorNumberFromContactPoint(point);

                    if (rNumber != null) {
                        rPointNumberParam.add(rNumber);
                    } else {
                        invalidPoint.add(point.key());
                    }

                } else if (point.getType().equals(PLCDataCode.PLC_DATA_REGISTER_CODE)) {
                    PLCDataRegisterNumber dNumber = dataRegisterNumberFromContactPoint(point);
                    System.out.println(dNumber);

                    if (dNumber != null) {
                        dPointNumberParam.add(dNumber);
                    } else {
                        invalidPoint.add(point.key());
                    }
                } else {
                    invalidPoint.add(point.key());
                }

            }
        }

        // 连续点转换
        if (sectionList != null) {
            for (ContactSection section : sectionList) {

                if (section.getType().equals(PLCContactorCode.PLC_INNER_RELAY_CODE)) {

                    ArrayList<PLCContactorNumber> rNumbers = contactorNumberListFromContactSection(section);
                    if (rNumbers != null) {
                        rPointNumberParam.addAll(rNumbers);
                    } else {
                        invalidPoint.add(section.getStartPoint() + " - " + section.getEndPoint());
                    }

                } else if (section.getType().equals(PLCDataCode.PLC_DATA_REGISTER_CODE)) {

                    PLCDataRegisterNumber dNumber = dataRegisterNumberFromContactSection(section);
                    if (dNumber != null) {
                        dPointNumberParam.add(dNumber);
                    } else {
                        invalidPoint.add(section.getStartPoint() + " - " + section.getEndPoint());
                    }

                } else {
                    invalidPoint.add(section.getStartPoint());
                    invalidPoint.add(section.getEndPoint());
                }
            }
        }

        HashMap<String, List> result = new HashMap<String, List>();
        result.put(D_NUMBER_KEY, dPointNumberParam);
        result.put(R_NUMBER_KEY, rPointNumberParam);
        result.put(ILLEGAL_KEY, invalidPoint);

        return result;
    }
    
    private String getLocationNumberFromStation(Station station) {
        String code = station.getCode();
        return code.substring(code.length() - 2, code.length());
    }

	/**
	 * 读取周期性采集点位数据
	 * 
	 * @param readRequest
	 * @return
	 */
	@RequestMapping(value= "/bufferRead", method = RequestMethod.POST)
	public ResponseEntity<PLCReadResponse> bufferRead(@RequestBody PLCReadRequest readRequest) {

        PLCReadResponse readResponse = new PLCReadResponse();
        readResponse.setDataMap(new HashMap<String, PLCPointData>());

        String collectorID = readRequest.getStation().getCode();
        

        try {

            // 获取采集器
            PLCCollector collector = (PLCCollector) Naming.lookup(collectorID);

            // 将请求中的请求参数转换为RMI接口参数

            // 离散点转换
            List<ContactPoint> pointList = readRequest.getPointList();
            List<ContactSection> sectionList = readRequest.getSectionList();

            // 转换函数
            HashMap<String, List> map = coreDataStructureFromWebDataStructure(pointList, sectionList);

            // 存储转换后的数据结构的数组
            ArrayList<PLCDataRegisterNumber> dPointNumberParam = (ArrayList<PLCDataRegisterNumber>) map.get(D_NUMBER_KEY);
            ArrayList<PLCContactorNumber> rPointNumberParam = (ArrayList<PLCContactorNumber>)map.get(R_NUMBER_KEY);
            ArrayList<String> ellegalPoints = (ArrayList<String>)map.get(ILLEGAL_KEY);

            // 存入非法点位
            for (String ellegalPoint: ellegalPoints) {
                readResponse.getDataMap().put(ellegalPoint, PLCPointData.errorData(PLCDataStatus.PLC_DATA_STATUS_ILLEGAL_POINT));
            }

            // 获取周期性结果
            PLCMissionResult rPointResult = null;
            PLCMissionResult dPointResult = null;

            if (!rPointNumberParam.isEmpty()) {
                rPointResult = collector.getCycleMissionResultFromContactorNumberArray(rPointNumberParam);
            }
            if (!dPointNumberParam.isEmpty()) {
                dPointResult = collector.getCycleMissionResultFromDataRegisterNumberArray(dPointNumberParam);
            }

            // 将周期性结果转换为Web数据结构
            if (rPointResult != null) {
                for (PLCData data : rPointResult.getResultData()) {
                    PLCPointData pointData = plcPointDataFromPlcData(data);
                    readResponse.getDataMap().put(pointData.getPointData().getContactPoint().getPoint() ,pointData);
                }
            }
            if (dPointResult != null) {
                for (PLCData data : dPointResult.getResultData()) {
                    PLCPointData pointData = plcPointDataFromPlcData(data);
                    readResponse.getDataMap().put(pointData.getPointData().getContactPoint().getPoint() ,pointData);
                }
            }

            // 设置响应的状态
            readResponse.setStatus((dPointResult == null? rPointResult.getResultType() : dPointResult.getResultType()));

        } catch (RemoteException e) {
            e.printStackTrace();
            readResponse.setStatus(RMIRemoteExceptionCode);

            readResponse.setTime(new Date());
            return new ResponseEntity<PLCReadResponse>(readResponse, HttpStatus.OK);
        } catch (NotBoundException e) {
            e.printStackTrace();
            readResponse.setStatus(RMINotBoundException);
            readResponse.setTime(new Date());
            return new ResponseEntity<PLCReadResponse>(readResponse, HttpStatus.OK);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            readResponse.setStatus(RMIMalformedURLException);
            readResponse.setTime(new Date());
            return new ResponseEntity<PLCReadResponse>(readResponse, HttpStatus.OK);
        }

        Date time = new Date();
        readResponse.setTime(time);
        return new ResponseEntity<PLCReadResponse>(readResponse, HttpStatus.OK);
    }
	
	
	/**
	 * 实时性读取点位数据
	 * 
	 * @param readRequest
	 * @return
	 */
	@RequestMapping(value= "/realtimeRead", method = RequestMethod.POST)
	public ResponseEntity<PLCReadResponse> realtimeRead(@RequestBody PLCReadRequest readRequest){

        PLCReadResponse readResponse = new PLCReadResponse();
        readResponse.setDataMap(new HashMap<String, PLCPointData>());


        // 业务 RMI

        String collectorID = readRequest.getStation().getCode();

        try {

            // 获取采集器
            PLCCollector collector = (PLCCollector) Naming.lookup(collectorID);

            // 将请求中的请求参数转换为RMI接口参数
            System.out.println("Ready to Convert");

            // 离散点转换
            List<ContactPoint> pointList = readRequest.getPointList();
            List<ContactSection> sectionList = readRequest.getSectionList();

            System.out.println("Start to Convert");
            // 转换函数
            HashMap<String, List> map = coreDataStructureFromWebDataStructure(pointList, sectionList);

            // 存储转换后的数据结构的数组
            ArrayList<PLCDataRegisterNumber> dPointNumberParam = (ArrayList<PLCDataRegisterNumber>) map.get(D_NUMBER_KEY);
            ArrayList<PLCContactorNumber> rPointNumberParam = (ArrayList<PLCContactorNumber>)map.get(R_NUMBER_KEY);
            ArrayList<String> ellegalPoints = (ArrayList<String>)map.get(ILLEGAL_KEY);

            // 存入非法点位
            for (String ellegalPoint: ellegalPoints) {
                readResponse.getDataMap().put(ellegalPoint, PLCPointData.errorData(PLCDataStatus.PLC_DATA_STATUS_ILLEGAL_POINT));
            }

            // 生成PLC任务
            PLCMission readMission = new PLCMission(readRequest.getRequestType(), PLCMission.PLCMISSION_PRIORITY_RTR_1);

            // 生成读取指令
            ArrayList<PLCRequestInstruction> requestInstructions = new ArrayList<PLCRequestInstruction>();

            // 获取站号
            String locationNumber = getLocationNumberFromStation(readRequest.getStation());

            if (!dPointNumberParam.isEmpty()) {

                for (PLCDataRegisterNumber dNumber : dPointNumberParam) {
                    PLCDataRegisterReadInstruction dri = new PLCDataRegisterReadInstruction();
                    dri.setLocationNumber_high(locationNumber.substring(0, 1));
                    dri.setLocationNumber_low(locationNumber.substring(1, 2));
                    dri.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);
                    dri.setDataRegisterNumber(dNumber);
                    requestInstructions.add(dri);
                }
            }
            if (!rPointNumberParam.isEmpty()) {
                int range = rPointNumberParam.size() / MULTI_R_POINT_MAX_NUMBER;
                range += (rPointNumberParam.size() % MULTI_R_POINT_MAX_NUMBER == 0 ? 0 : 1);
                int index = 0;

                for (int i = 0; i < range; ++i) {
                    PLCMultipleContactorReadInstruction mri = new PLCMultipleContactorReadInstruction();
                    mri.setLocationNumber_high(locationNumber.substring(0, 1));
                    mri.setLocationNumber_low(locationNumber.substring(1, 2));

                    ArrayList<PLCContactorNumber> rNumberList = new ArrayList<PLCContactorNumber>();
                    ArrayList<String> rPointCodeList = new ArrayList<String>();

                    if (i != range - 1) {
                        mri.setCount(MULTI_R_POINT_MAX_NUMBER);

                        int maxJ = index + MULTI_R_POINT_MAX_NUMBER;
                        for (int j = index; j < maxJ; ++j) {
                            rNumberList.add(rPointNumberParam.get(j));
                            rPointCodeList.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
                        }

                        mri.setContactorCodes(rPointCodeList);
                        mri.setContactorNumbers(rNumberList);
                    } else {
                        int remainder = rPointNumberParam.size() % MULTI_R_POINT_MAX_NUMBER;
                        int remain = (remainder == 0? MULTI_R_POINT_MAX_NUMBER : remainder);

                        mri.setCount(remain);

                        int maxJ = index + remain;
                        for (int j = index; j < maxJ; ++j) {
                            rNumberList.add(rPointNumberParam.get(j));
                            rPointCodeList.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
                        }
                    }

                    index += MULTI_R_POINT_MAX_NUMBER;

                    mri.setContactorCodes(rPointCodeList);
                    mri.setContactorNumbers(rNumberList);
                    mri.setBBC();
                    requestInstructions.add(mri);
                }
            }

            // 获取实时读取结果
            readMission.setInstructions(requestInstructions);
            for (PLCRequestInstruction i : requestInstructions) {
                System.out.println(i);
            }
            PLCMissionResult readResult = collector.addRealtimeReadMission(readMission);
            System.out.println("Result: " + readResult);

            // 转换为Web数据结构
            if (readResult != null) {
                for (PLCData data : readResult.getResultData()) {
                    PLCPointData pointData = plcPointDataFromPlcData(data);
                    readResponse.getDataMap().put(pointData.getPointData().getContactPoint().getPoint() ,pointData);
                }
                // 设置响应的状态
                readResponse.setStatus(readResult.getResultType());
            } else {
                // 设置响应的状态
                readResponse.setStatus(CannotFindResult);
            }

        } catch (RemoteException e) {
            e.printStackTrace();
            readResponse.setStatus(RMIRemoteExceptionCode);
        } catch (NotBoundException e) {
            e.printStackTrace();
            readResponse.setStatus(RMINotBoundException);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            readResponse.setStatus(RMIMalformedURLException);
        }

        Date time = new Date();
        readResponse.setTime(time);
		return new ResponseEntity<PLCReadResponse>(readResponse,HttpStatus.OK);
	}
	
	/**
	 * 实时性写入点位数据
	 * 
	 * @param writeRequest
	 * @return
	 */

	@RequestMapping(value= "/realtimeWrite", method = RequestMethod.POST)
	public ResponseEntity<PLCWriteResponse> realtimeWrite(@RequestBody PLCWriteRequest writeRequest){

        PLCWriteResponse writeResponse = new PLCWriteResponse();
        writeResponse.setDataMap(new HashMap<String, PLCPointData>());

        // 业务 RMI

        String collectorID = writeRequest.getStation().getCode();

        try {

            // 获取采集器
            PLCCollector collector = (PLCCollector) Naming.lookup(collectorID);

            // 需要写入的点位
            ArrayList<PLCContactorNumber> rPointList = new ArrayList<PLCContactorNumber>();
            ArrayList<PLCDataRegisterNumber> dPointList = new ArrayList<PLCDataRegisterNumber>();
            ArrayList<String> invalidPoints = new ArrayList<>();

            // 写入数据Map
            HashMap<String, String> writeValues = new HashMap<String, String>();

            // 将请求中的请求参数转换为RMI接口参数
            for (ContactPointData writePoint : writeRequest.getDataList()) {

                if (writePoint.getContactPoint().getType().equals(PLCContactorCode.PLC_INNER_RELAY_CODE)) {
                    PLCContactorNumber rNumber = contactorNumberFromContactPoint(writePoint.getContactPoint());

                    if (rNumber != null) {
                        rPointList.add(rNumber);
                        writeValues.put(rNumber.toString(), writePoint.getValue());
                    } else {
                        invalidPoints.add(writePoint.getContactPoint().key());
                    }
                } else if (writePoint.getContactPoint().getType().equals(PLCDataCode.PLC_DATA_REGISTER_CODE)) {
                    PLCDataRegisterNumber dNumber = dataRegisterNumberFromContactPoint(writePoint.getContactPoint());

                    if (dNumber != null) {
                        dPointList.add(dNumber);
                        writeValues.put(dNumber.toString(), writePoint.getValue());
                    } else {
                        invalidPoints.add(writePoint.getContactPoint().key());
                    }
                } else {
                    invalidPoints.add(writePoint.getContactPoint().key());
                }
            }

            for (String invalidPoint : invalidPoints) {
                // 存入非法点位
                writeResponse.getDataMap().put(invalidPoint, PLCPointData.errorData(PLCDataStatus.PLC_DATA_STATUS_ILLEGAL_POINT));
            }

            for (String key : writeResponse.getDataMap().keySet()) {
                System.out.println(key + " " + writeResponse.getDataMap().get(key));
            }

            // 构造任务
            PLCMission writeMission = new PLCMission(writeRequest.getRequestType(), PLCMission.PLCMISSION_PRIORITY_RTW_0);

            // 生成写入指令
            ArrayList<PLCRequestInstruction> requestInstructions = new ArrayList<PLCRequestInstruction>();

            // 获取站号
            String locationNumber = getLocationNumberFromStation(writeRequest.getStation());

            if (!rPointList.isEmpty()) {
                int range = rPointList.size() / MULTI_R_POINT_MAX_NUMBER;
                range += (rPointList.size() % MULTI_R_POINT_MAX_NUMBER == 0 ? 0 : 1);
                int index = 0;
                for (int i = 0; i < range; ++i) {
                    PLCMultipleContactorWriteInstruction mri = new PLCMultipleContactorWriteInstruction();
                    mri.setLocationNumber_high(locationNumber.substring(0, 1));
                    mri.setLocationNumber_low(locationNumber.substring(1, 2));

                    ArrayList<PLCContactorNumber> rNumberList = new ArrayList<PLCContactorNumber>();
                    ArrayList<String> rPointCodeList = new ArrayList<String>();
                    ArrayList<String> insWriteValues = new ArrayList<String>();

                    if (i != range - 1) {
                        mri.setCount(MULTI_R_POINT_MAX_NUMBER);

                        int maxJ = index + MULTI_R_POINT_MAX_NUMBER;
                        for (int j = index; j < maxJ; ++j) {
                            PLCContactorNumber rNumber = rPointList.get(j);
                            rNumberList.add(rNumber);
                            rPointCodeList.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
                            insWriteValues.add(writeValues.get(rNumber.toString()));
                        }

                        mri.setContactorCodes(rPointCodeList);
                        mri.setContactorNumbers(rNumberList);
                    } else {
                        int remainder = rPointList.size() % MULTI_R_POINT_MAX_NUMBER;
                        int remain = (remainder == 0 ? MULTI_R_POINT_MAX_NUMBER : remainder);

                        mri.setCount(remain);

                        int maxJ = index + remain;
                        for (int j = index; j < maxJ; ++j) {
                            PLCContactorNumber rNumber = rPointList.get(j);
                            rNumberList.add(rNumber);
                            rPointCodeList.add(PLCContactorCode.PLC_INNER_RELAY_CODE);
                            insWriteValues.add(writeValues.get(rNumber.toString()));
                        }
                    }

                    index += MULTI_R_POINT_MAX_NUMBER;

                    mri.setContactorCodes(rPointCodeList);
                    mri.setContactorNumbers(rNumberList);
                    mri.setWriteData(insWriteValues);
                    mri.setBBC();
                    requestInstructions.add(mri);
                }
            }
            if (!dPointList.isEmpty()) {
                for (PLCDataRegisterNumber dNumber : dPointList) {
                    PLCDataRegisterWriteInstruction rwi = new PLCDataRegisterWriteInstruction();
                    rwi.setLocationNumber_high(locationNumber.substring(0, 1));
                    rwi.setLocationNumber_low(locationNumber.substring(1, 2));
                    rwi.setDataCode(PLCDataCode.PLC_DATA_REGISTER_CODE);
                    rwi.setDataRegisterNumber(dNumber);

                    ArrayList<String> writeDatas = new ArrayList<String>();
                    writeDatas.add(writeValues.get(dNumber.toString()));
                    rwi.setWriteData(writeDatas);
                    rwi.setBBC();

                    requestInstructions.add(rwi);
                }
            }

            for (PLCRequestInstruction i : requestInstructions) {
                System.out.println(i);
            }

            // 获取实时写入结果
            writeMission.setInstructions(requestInstructions);
            PLCMissionResult writeResult = collector.addRealtimeWriteMission(writeMission);

            // 转换为Web数据结构
            if (writeResult != null) {
                for (PLCData data : writeResult.getResultData()) {
                    PLCPointData pointData = plcPointDataFromPlcData(data);
                    writeResponse.getDataMap().put(pointData.getPointData().getContactPoint().getPoint() ,pointData);
                }
                // 设置响应的状态
                writeResponse.setStatus(writeResult.getResultType());
            }else {
                // 设置响应的状态
                writeResponse.setStatus(CannotFindResult);
            }



        } catch (RemoteException e) {
            e.printStackTrace();
            writeResponse.setStatus(RMIRemoteExceptionCode);
        } catch (NotBoundException e) {
            e.printStackTrace();
            writeResponse.setStatus(RMINotBoundException);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            writeResponse.setStatus(RMIMalformedURLException);
        }

        Date time = new Date();
        writeResponse.setTime(time);
		return new ResponseEntity<PLCWriteResponse>(writeResponse,HttpStatus.OK);
	}

    private PLCStatusData plcStatusDataFromPlcCollectorStatus(PLCCollectorStatus collectorStatus) {

        PLCStatusData statusData = new PLCStatusData();
        statusData.setStatus(collectorStatus.getState());

        StationStatus stationStatus = new StationStatus();
        stationStatus.setStartTime(collectorStatus.getCollectorStartTime());
        stationStatus.setStatus(PLCStatusData.PLC_STATIONC_EXIST);

        HashMap<String, StationQueueStatus> queueStatusHashMap = new HashMap<String, StationQueueStatus>();
        queueStatusHashMap.put(StationStatus.CYCLE_QUEUE_KEY, stationQueueStatusFromPLCQueueStatus(collectorStatus.getCycleQueueState()));
        queueStatusHashMap.put(StationStatus.RTW_QUEUE_KEY, stationQueueStatusFromPLCQueueStatus(collectorStatus.getRealTimeWriteQueueState()));
        queueStatusHashMap.put(StationStatus.RTR_QUEUE_KEY, stationQueueStatusFromPLCQueueStatus(collectorStatus.getRealTimeReadQueueState()));

        stationStatus.setQueueStatus(queueStatusHashMap);
        statusData.setData(stationStatus);

        return statusData;
    }

    private StationQueueStatus stationQueueStatusFromPLCQueueStatus(PLCCollectorQueueStatus queueStatus) {

        StationQueueStatus stationQueueStatus = new StationQueueStatus();

        stationQueueStatus.setIndexOfCurrentIns(queueStatus.getIndexOfCurrentIns());
        stationQueueStatus.setInstructionPriority(queueStatus.getInstructionPriority());
        stationQueueStatus.setNumberOfFinishIns(queueStatus.getNumberOfFinishIns());
        stationQueueStatus.setNumberOfRemainIns(queueStatus.getNumberOfRemainIns());

        return stationQueueStatus;
    }
	
	/**
	 * 查询PLC站点的状态信息
	 * 
	 * @param statusRequest
	 * @return
	 */

	@RequestMapping(value= "/queryStatus", method = RequestMethod.POST)
	public ResponseEntity<PLCStatusResponse> queryStatus(@RequestBody PLCStatusRequest statusRequest){

        PLCStatusResponse statusResponse = new PLCStatusResponse();
        statusResponse.setDataMap(new HashMap<String, PLCStatusData>());

        // 业务 RMI

        PLCMaster master = null;
		try {
            master = (PLCMaster) Naming.lookup(PLCMaster.NAME);
            HashMap<String, PLCStatusData> statusMap = new HashMap<String, PLCStatusData>();

            for (Station station : statusRequest.getStationList()) {
                PLCCollectorStatus collectorStatus = master.getCollectorStateFromID(station.getCode());

                if (collectorStatus == null) {

                    PLCStatusData statusData = new PLCStatusData();
                    statusData.setStatus(PLCStatusData.PLC_STATIONC_NOT_EXIST);
                    statusMap.put(station.toString(), statusData);

                } else {
                    statusMap.put(station.toString(), plcStatusDataFromPlcCollectorStatus(collectorStatus));
                }
            }

            statusResponse.setDataMap(statusMap);

        } catch (RemoteException e) {
            e.printStackTrace();
            statusResponse.setStatus(RMIRemoteExceptionCode);
        } catch (NotBoundException e) {
            e.printStackTrace();
            statusResponse.setStatus(RMINotBoundException);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            statusResponse.setStatus(RMIMalformedURLException);
        }

        return new ResponseEntity<PLCStatusResponse>(statusResponse,HttpStatus.OK);
	}

	
	public ResponseEntity<PLCReadResponse> read(@RequestBody PLCReadRequest readRequest){
		return null;
	}

}
